#include <iostream>
#include <concepts>
#include <vector>
#include <list>
#include <string>
#include <type_traits>

// 自定义概念：定义一个表示可哈希类型的概念
template<typename T>
concept Hashable = requires(T a) {
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};

// 使用标准库提供的概念
template<std::integral T>
T gcd(T a, T b) {
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

// 自定义概念：定义一个表示有序容器的概念
template<typename T>
concept OrderedContainer = requires(T container) {
    typename T::value_type;
    requires std::ranges::forward_range<T>;
    requires requires(typename T::iterator it) { ++it; };
    { container.begin() } -> std::same_as<typename T::iterator>;
    { container.end() } -> std::same_as<typename T::iterator>;
    { container.size() } -> std::convertible_to<std::size_t>;
};

// 使用自定义概念的函数
template<OrderedContainer T>
void print_container(const T& container) {
    std::cout << "  容器内容: ";
    for (const auto& item : container) {
        std::cout << item << " ";
    }
    std::cout << '\n';
}

// 结合约束参数
template<typename T>
    requires std::integral<T> || std::floating_point<T>
T add(T a, T b) {
    return a + b;
}

// 概念和auto结合
auto add_hashables(Hashable auto a, Hashable auto b) {
    std::hash<decltype(a)> hasher_a;
    std::hash<decltype(b)> hasher_b;
    std::cout << "  哈希值: " << hasher_a(a) << " + " << hasher_b(b) << '\n';
    
    if constexpr (std::is_same_v<decltype(a), decltype(b)> && 
                 (std::is_integral_v<decltype(a)> || 
                  std::is_floating_point_v<decltype(a)> ||
                  std::is_same_v<decltype(a), std::string>)) {
        return a + b;
    } else {
        return hasher_a(a) + hasher_b(b);
    }
}

// 多个概念约束
template<typename T>
    requires std::integral<T> && std::unsigned_integral<T>
T factorial(T n) {
    T result = 1;
    for (T i = 2; i <= n; ++i) {
        result *= i;
    }
    return result;
}

// 约束模板类
template<typename T>
    requires std::default_initializable<T> && std::copy_constructible<T>
class Container {
private:
    std::vector<T> m_data_;
    
public:
    void add(const T& item) {
        m_data_.push_back(item);
    }
    
    void print() const {
        std::cout << "  容器元素: ";
        for (const auto& item : m_data_) {
            std::cout << item << " ";
        }
        std::cout << '\n';
    }
};

// 使用requires表达式进行复杂约束
template<typename T>
    requires requires(T x) {
        { x + x } -> std::same_as<T>;
        { x - x } -> std::same_as<T>;
        { x * x } -> std::same_as<T>;
        { x / x } -> std::same_as<T>;
    }
T arithmetic_operations(T a, T b) {
    return (a + b) * (a - b) / (a * b);
}

void demonstrate_concepts() {
    std::cout << "  C++20 概念(Concepts)演示:\n\n";
    
    // 1. 标准库概念 std::integral
    std::cout << "  标准库概念 - std::integral:\n";
    std::cout << "  gcd(12, 18) = " << gcd(12, 18) << '\n';
    // 以下会编译错误，因为double不满足std::integral概念
    // std::cout << "gcd(12.5, 18.5) = " << gcd(12.5, 18.5) << '\n';
    
    // 2. 自定义概念 OrderedContainer
    std::cout << "\n  自定义概念 - OrderedContainer:\n";
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::list<double> lst = {1.1, 2.2, 3.3, 4.4};
    
    print_container(vec);
    print_container(lst);
    
    // 3. 结合约束参数
    std::cout << "\n  约束参数:\n";
    std::cout << "  add(1, 2) = " << add(1, 2) << '\n';
    std::cout << "  add(3.14, 2.71) = " << add(3.14, 2.71) << '\n';
    
    // 4. 概念和auto结合
    std::cout << "\n  概念和auto结合:\n";
    std::string str1 = "Hello";
    std::string str2 = "World";
    std::cout << "  add_hashables(\"" << str1 << "\", \"" << str2 << "\") = " 
              << add_hashables(str1, str2) << '\n';
    
    std::cout << "  add_hashables(42, 13) = " << add_hashables(42, 13) << '\n';
    
    // 5. 多个概念约束
    std::cout << "\n  多个概念约束:\n";
    std::cout << "  factorial(5) = " << factorial(5u) << '\n';
    // 以下会编译错误，因为-5不满足std::unsigned_integral概念
    // std::cout << "factorial(-5) = " << factorial(-5) << '\n';
    
    // 6. 约束模板类
    std::cout << "\n  约束模板类:\n";
    Container<int> int_container;
    int_container.add(10);
    int_container.add(20);
    int_container.add(30);
    int_container.print();
    
    // 7. 复杂的requires表达式
    std::cout << "\n  复杂的requires表达式:\n";
    std::cout << "  arithmetic_operations(5, 3) = " 
              << arithmetic_operations(5, 3) << '\n';
              
    // 概念的编译期检查性质
    std::cout << "\n  概念的编译期检查:\n";
    std::cout << "  std::integral<int>: " << std::boolalpha 
              << std::integral<int> << '\n';
    std::cout << "  std::integral<double>: " 
              << std::integral<double> << '\n';
    std::cout << "  std::floating_point<double>: " 
              << std::floating_point<double> << '\n';
    std::cout << "  std::same_as<int, int>: " 
              << std::same_as<int, int> << '\n';
    std::cout << "  std::same_as<int, long>: " 
              << std::same_as<int, long> << '\n';
} 